# -*- coding: utf-8 -*-
import sys

from PyQt5.QtCore import Qt, QRectF
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *


class RotateMeter(QWidget):
    def __init__(self, *args, **kwargs):
        text = kwargs.pop("text", "")
        super(RotateMeter, self).__init__(*args, **kwargs)
        self.InitUI()

    def InitUI(self):
        # 输入量
        self.altitudeThetaDeg = 0  # 俯仰角
        self.altitudePhiDeg = 0  # 滚转角
        self.windAglBeta = 0  # 侧滑角
        # 俯仰角刻度尺属性
        self.viewLength = 40  # 量程
        self.startValue = self.altitudeThetaDeg - self.viewLength / 2  # 起始位置对应取值
        self.endValue = self.startValue + self.viewLength  # 终止位置对应取值
        self.scaleLenRatio = 0.6  # 刻度尺长度区域
        self.quarterLineLen = 0.05  # 2.5°刻度标记长度
        self.halfLineLen = 0.10  # 5°刻度标记长度
        self.tenDegLineLen = 0.14  # 10°刻度标记长度

        self.rollScaleRadiusRatio = 0.34  # 滚转角刻度环半径，0 ~ 0.5占据高度区域
        self.rollHalfScaleLen = 0.04  # 滚转角短刻度线长，相对于圆环半径的长度
        self.rollMainScaleLen = 0.08  # 滚转角长刻度线长，相对于圆环半径长度

        # 背景区域设置
        self.bgWidth = 400
        self.bgHeight = 400
        self.bgSkyColor = QColor(20, 81, 249)
        self.bgGroundColor = QColor(83, 53, 7)
        # 设置字符
        self.fontName = "Noto Sans S Chinese Bold"
        self.fontSize = 12
        # self.font = QFont(, 10)  # 读数文字字体
        self.TextColor = QColor(255, 255, 255, 255)  # 刻度值文字显示颜色

        # 窗口属性
        self.setMinimumSize(self.bgWidth, self.bgHeight)

    # 设置俯仰角
    def setThetaDeg(self, theta_deg):

        self.altitudeThetaDeg = theta_deg

        # 俯仰角刻度位置根据俯仰角取值进行更新
        self.startValue = self.altitudeThetaDeg - self.viewLength / 2  # 起始位置对应取值
        self.endValue = self.startValue + self.viewLength  # 终止位置对应取值

        # 更新绘图
        self.update()

    def setPhiDeg(self, phi_deg):
        self.altitudePhiDeg = -phi_deg
        self.update()

    def paintEvent(self, event):
        width = self.width()
        height = self.height()

        painter = QPainter(self)  # 初始化painter
        painter.translate(width / 2, height / 2)  # 坐标轴变换，调用translate()将坐标原点平移至窗口中心

        # 坐标刻度自适应
        # side = min(width, height)
        # painter.scale(side / self.bgWidth, side / self.bgWidth)
        self.bgWidth = width
        self.bgHeight = height
        # 本项目中将坐标缩小为side/200倍，即画出length=10的直线，其实际长度应为10*(side/200)。
        painter.setClipRect(QRectF(-self.bgWidth / 2, -self.bgHeight / 2, self.bgWidth, self.bgHeight),
                            Qt.IntersectClip)
        # 启用反锯齿，使画出的曲线更平滑
        painter.setRenderHints(QPainter.Antialiasing | QPainter.TextAntialiasing)
        painter.begin(self)

        # 开始画图
        self.drawBackGround(painter)
        self.drawThetaScaleLine(painter)
        self.drawRollScaleLine(painter)
        self.drawIndicator(painter)

        painter.end()

    def drawBackGround(self, painter):  # 背景区域绘制
        painter.save()
        painter.rotate(self.altitudePhiDeg)  # 根据滚转角旋转背景,要先旋转再平移，否则会出现错位
        painter.translate(0,
                          self.scaleLenRatio * self.bgHeight * self.altitudeThetaDeg / self.viewLength)  # 根据俯仰角设置纵向偏移

        painter.setPen(Qt.NoPen)
        brush = QBrush(Qt.SolidPattern)
        brush.setColor(self.bgSkyColor)
        painter.setBrush(brush)
        painter.drawRect(-self.bgWidth * 2, -self.bgHeight * 2, self.bgWidth * 4, self.bgHeight * 2)

        brush.setColor(self.bgGroundColor)
        painter.setBrush(brush)
        painter.drawRect(-self.bgWidth * 2, 0, self.bgWidth * 4, self.bgHeight * 2)

        pen = QPen(Qt.white, 2, Qt.SolidLine)
        painter.setPen(pen)
        painter.drawLine(-self.bgWidth, 0, self.bgWidth, 0)

        painter.restore()

    def drawIndicator(self, painter):
        painter.save()
        # pen = QPen(QColor(255, 255, 0, 255), 2, Qt.SolidLine)

        self.indicatorColor = QColor(255, 255, 0)  # 指示器颜色
        self.centerIndicatorRadious = 0.01  # 俯仰角指示中间圆点半径占据高度范围 0~1
        self.indicatorBorderColor = QColor(0, 0, 0)  # 边框颜色

        painter.setPen(QPen(self.indicatorBorderColor, 1.5, Qt.SolidLine))
        painter.setBrush(self.indicatorColor)

        radious = self.centerIndicatorRadious * self.bgHeight

        # 绘制俯仰角指示器中间圆点
        rect = QRectF(-radious, -radious, radious * 2, radious * 2)
        # painter.drawPie(rect, 0 * 16, 360 * 16)
        painter.drawEllipse(rect)
        # 绘制多边形指示器
        # 左侧
        self.levelIndicatorStart = 0.15
        self.levelIndicatorEnd = 0.36
        offset_x = self.levelIndicatorStart * self.bgWidth
        length = (self.levelIndicatorEnd - self.levelIndicatorStart) * self.bgWidth
        step_height = 0.02 * self.bgHeight
        step_width = 0.015 * self.bgWidth
        height = 0.015 * self.bgHeight
        scale_radius = self.rollScaleRadiusRatio * self.bgHeight  # 滚转角指示刻度环半径
        betaoffset = self.windAglBeta / 90 * scale_radius  # 侧滑角对应的侧偏指示器偏移
        # 右侧
        pts = QPolygon()
        pts.setPoints(0, 0,
                      -length, 0,
                      -length, height,
                      -step_width, height,
                      -step_width, height + step_height,
                      0, height + step_height)
        painter.translate(-offset_x, 0)
        painter.drawConvexPolygon(pts)

        # 绘制滚转角指示器
        pts.setPoints(0, 0,
                      length, 0,
                      length, height,
                      step_width, height,
                      step_width, height + step_height,
                      0, height + step_height)
        painter.translate(offset_x * 2, 0)
        painter.drawConvexPolygon(pts)

        pts.setPoints(-scale_radius * 0.05, 0,
                      scale_radius * 0.05, 0,
                      0, -scale_radius * 0.08)
        painter.translate(-offset_x, -self.rollScaleRadiusRatio * self.bgHeight + scale_radius * 0.08)
        painter.setPen(Qt.NoPen)
        painter.setBrush(QColor(255, 255, 255))
        painter.drawConvexPolygon(pts)

        pts.setPoints(-scale_radius * 0.06, 0,
                      -scale_radius * 0.08, scale_radius * 0.02,
                      scale_radius * 0.08, scale_radius * 0.02,
                      scale_radius * 0.06, 0)
        painter.translate(betaoffset, scale_radius * 0.02)
        painter.setPen(Qt.NoPen)
        painter.setBrush(QColor(255, 255, 255))
        painter.drawConvexPolygon(pts)

        painter.restore()

    def drawThetaScaleLine(self, painter):  # 画出刻度和刻度文字
        painter.save()
        painter.rotate(self.altitudePhiDeg)  # 根据滚转角旋转背景

        # 绘制刻度线
        painter.setFont(QFont(self.fontName, self.fontSize))  # 读数文字字体
        totalheight = self.bgHeight * self.scaleLenRatio
        # totallen = self.bgWidth
        start_value = self.startValue
        end_value = self.endValue
        view_length = self.viewLength  # 可视区域长度 = end_value - start_value
        text_width = self.fontMetrics().width("%3d" % 90) * 1.2
        text_height = self.fontMetrics().height()

        quarter_line_len = self.quarterLineLen * self.bgWidth
        half_line_len = self.halfLineLen * self.bgWidth
        ten_deg_line_len = self.tenDegLineLen * self.bgWidth
        painter.setClipRect(QRectF(-self.bgWidth / 2, -totalheight / 2, self.bgWidth, totalheight),
                            Qt.IntersectClip)

        unit = 2.5  # 2.5°四分之一刻度线
        tmp_scale_value = (int(start_value / unit) - 1) * unit
        painter.setPen(QPen(QColor(255, 255, 255, 255), 1, Qt.SolidLine))
        while tmp_scale_value < end_value + unit:
            # 画刻度线
            pos = totalheight / 2 - (tmp_scale_value - start_value) / view_length * totalheight
            painter.drawLine(-quarter_line_len / 2, pos, quarter_line_len / 2, pos)  # 画出刻度线
            tmp_scale_value = tmp_scale_value + unit

        unit = 5
        tmp_scale_value = (int(start_value / unit) - 1) * unit
        # painter.setPen(QPen(QColor(255, 255, 255), 1, Qt.SolidLine))
        while tmp_scale_value < end_value + unit:
            # 画刻度线
            pos = totalheight / 2 - (tmp_scale_value - start_value) / view_length * totalheight
            painter.drawLine(-half_line_len / 2, pos, half_line_len / 2, pos)  # 画出刻度线
            tmp_scale_value = tmp_scale_value + unit

        unit = 10
        tmp_scale_value = (int(start_value / unit) - 1) * unit
        # painter.setPen(QPen(QColor(255, 255, 255, 255), 1, Qt.SolidLine))
        while tmp_scale_value < end_value + unit:
            # 画刻度线
            pos = totalheight / 2 - (tmp_scale_value - start_value) / view_length * totalheight
            painter.drawLine(-ten_deg_line_len / 2, pos, ten_deg_line_len / 2, pos)  # 画出刻度线

            # painter.setPen(self.scaleTextColor)  # 设置文字颜色
            # 画刻度文字
            str_value = "%3d" % int(tmp_scale_value)
            rectf = QRectF(-ten_deg_line_len / 2 - text_width * 1.1, pos - text_height / 2, text_width, text_height)
            painter.drawText(rectf, Qt.AlignVCenter | Qt.AlignRight, str_value)

            rectf = QRectF(ten_deg_line_len / 2, pos - text_height / 2, text_width, text_height)
            painter.drawText(rectf, Qt.AlignVCenter | Qt.AlignLeft, str_value)

            tmp_scale_value = tmp_scale_value + unit

        painter.restore()

    def drawRollScaleLine(self, painter):
        painter.save()
        painter.rotate(self.altitudePhiDeg)  # 根据滚转角旋转背景
        scale_radius = self.rollScaleRadiusRatio * self.bgHeight  # 滚转角指示刻度环半径
        half_scale_len = self.rollHalfScaleLen * scale_radius  # 滚转角指示刻度细值长度 -45，-20，-10，0，10，20，45
        main_scale_len = self.rollMainScaleLen * scale_radius  # 滚转角指示刻度粗值长度 -60，-50，50，60

        # 绘制滚转角刻度环
        painter.setPen(QPen(QColor(255, 255, 255, 255), 2, Qt.SolidLine))
        rect = QRectF(-scale_radius, -scale_radius, scale_radius * 2, scale_radius * 2)
        painter.drawArc(rect, 30 * 16, 120 * 16)  # 绘画角度为30°~(30+150°)

        # 绘制滚转角刻度线
        painter.rotate(-60)  # -60
        painter.drawLine(0, -scale_radius, 0, -scale_radius - main_scale_len)
        painter.rotate(15)  # -45
        painter.drawLine(0, -scale_radius, 0, -scale_radius - half_scale_len)
        painter.rotate(15)  # -30
        painter.drawLine(0, -scale_radius, 0, -scale_radius - main_scale_len)
        painter.rotate(10)  # -20
        painter.drawLine(0, -scale_radius, 0, -scale_radius - half_scale_len)
        painter.rotate(10)  # -10
        painter.drawLine(0, -scale_radius, 0, -scale_radius - half_scale_len)

        painter.rotate(10)  # 0 # 绘制三角形
        # painter.drawLine(0, -scale_radius, 0, -scale_radius - 2)

        painter.rotate(10)  # 10
        painter.drawLine(0, -scale_radius, 0, -scale_radius - half_scale_len)
        painter.rotate(10)  # 20
        painter.drawLine(0, -scale_radius, 0, -scale_radius - half_scale_len)
        painter.rotate(10)  # 30
        painter.drawLine(0, -scale_radius, 0, -scale_radius - main_scale_len)
        painter.rotate(15)  # 45
        painter.drawLine(0, -scale_radius, 0, -scale_radius - half_scale_len)
        painter.rotate(15)  # 60
        painter.drawLine(0, -scale_radius, 0, -scale_radius - main_scale_len)

        painter.rotate(-60)
        painter.setPen(Qt.NoPen)
        painter.setBrush(QColor(255, 255, 255, 255))
        # 绘制多边形做指针
        pts = QPolygon()
        pts.setPoints(0, -scale_radius,
                      -scale_radius * 0.05, -scale_radius * 1.08,
                      scale_radius * 0.05, -scale_radius * 1.08)
        painter.drawConvexPolygon(pts)
        painter.restore()  # 恢复painter的状态


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = RotateMeter()
    # demo.InitUI()
    demo.show()
    demo.setGeometry(100, 100, 400, 400)
    demo.setThetaDeg(30)  # 设置指针指向
    demo.setPhiDeg(15)
    # demo.setTargetValue(88.5)

    # demo.setValue(200)
    # demo.setTitle("Title_____")  # 设置图标题
    sys.exit(app.exec_())
